﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AAA.Chart.Data;
using AAA.Chart.Component;
using AAA.Chart.Style;
using System.Drawing;
using AAA.Meta.Chart;

namespace AAA.Chart.Indicator
{
    public abstract class DefaultIndicator : IIndicator
    {
        #region IIndicator Members

        private IDataSource _dsDataSource;
        private IChartMeta _cmChartMeta;
        private ChartStyleEnum _eChartType;
        private string _strBaseStudy;
        private IDrawMethod _drawMethod;
        public abstract void Calculate();
        private List<float> _lstDataSource1;
        private List<float> _lstDataSource2;
        private List<float> _lstDataSource3;
        private List<float> _lstDataSource4;

        private List<float> _lstXMax;
        private List<float> _lstXMin;
        private List<float> _lstYMax;
        private List<float> _lstYMin;
        private float _fCustomXMin = float.NaN;
        private float _fCustomYMin = float.NaN;

        private int _iStartIndex;
        private int _iEndIndex;
        private int _iXAxis = ChartConstants.X;
        private int _iYAxis = ChartConstants.Y;
        private int _iXDataType = ChartConstants.DATA_TYPE_TIME;
        private bool _isScrollable = true;
        private List<ChartText> _lstText;

        private string _strName;
        private DataTypeEnum _eDataField;
        
        public DefaultIndicator()
        {
            _lstText = new List<ChartText>();
        }

        public void Draw(Graphics g)
        {
            //Calculate();
            if (_drawMethod == null)
                return;
            _drawMethod.Draw(g);

            Pen pen;

            foreach (ChartText chartText in _lstText)
            {
                pen = new Pen(new SolidBrush(chartText.ForeColor));
                int[] iPoint;

                iPoint = ChartMeta.ValueToPixel(chartText.XValue, chartText.YValue);

                g.DrawString(chartText.Text, 
                             new Font("Arial", 8, FontStyle.Regular), 
                             new SolidBrush(chartText.ForeColor), 
                             new PointF(iPoint[0], iPoint[1]));
            }
        }

        public void ClearChartText()
        {
            _lstText = new List<ChartText>();
        }

        public void DrawText(float fXValue, float fYValue, string strText, Color cForeColor)
        {
            ChartText chartText = new ChartText();

            chartText.XValue = fXValue;
            chartText.YValue = fYValue;
            chartText.Text = strText;
            chartText.ForeColor = cForeColor;

            _lstText.Add(chartText);
        }

        public void Plot(List<float> lstDataSource, string strName, Color cForeColor, Color cBackColor, int iWidth)
        {
            List<float> lstXValue = new List<float>();

            for (int i = 0; i < lstDataSource.Count; i++)
                lstXValue.Add(i);

            Plot(lstXValue, lstDataSource, strName, cForeColor, cBackColor, iWidth);
        }

        public void Plot(List<float> lstXDataSource, List<float> lstYDataSource, string strName, Color cForeColor, Color cBackColor, int iWidth)
        {
            Plot(lstXDataSource, lstYDataSource, null, strName, cForeColor, cBackColor, iWidth);
        }

        public void Plot(List<float> lstXDataSource, List<float> lstYDataSource, List<float> lstTimeDataSource, string strName, Color cForeColor, Color cBackColor, int iWidth)
        {
            _lstXMax = lstXDataSource;
            _lstXMin = lstXDataSource;
            _lstYMax = lstYDataSource;
            _lstYMin = lstYDataSource;
            Plot(lstXDataSource, lstYDataSource, lstTimeDataSource, null, strName, cForeColor, cBackColor, iWidth);
        }

        public void Plot(List<float> lstOpen, List<float> lstHigh, List<float> lstLow, List<float> lstClose, string strName, Color cForeColor, Color cBackColor, int iWidth)
        {
            _drawMethod.LastPrice = _dsDataSource.LastPrice(BaseStudy);
            _drawMethod.LastVolume = _dsDataSource.LastVolume(BaseStudy);
            _drawMethod.Plot(lstOpen, lstHigh, lstLow, lstClose, strName, cForeColor, cBackColor, iWidth);

            _drawMethod.ChartMeta = ChartMeta;
            _lstDataSource1 = lstOpen;
            _lstDataSource2 = lstHigh;
            _lstDataSource3 = lstLow;
            _lstDataSource4 = lstClose;

            if (lstHigh != null)
                _lstYMax = lstHigh;

            if (lstLow != null)
                _lstYMin = lstLow;

            if (_lstXMin == null)
            {
                _lstXMin = new List<float>();
                _lstXMax = new List<float>();
                for (int i = 0; i < lstOpen.Count; i++)
                {
                    _lstXMin.Add(i);
                    _lstXMax.Add(i);
                }
            }

            _drawMethod.StartIndex = StartIndex;
            _drawMethod.EndIndex = EndIndex;
        }
/*
        public float GetYMax(int iStartIndex, int iEndIndex)
        {
            float fMax = -float.MaxValue;

            if (_lstDataSource == null)
                return fMax;

            for (int i = iStartIndex; i < iEndIndex; i++)
                fMax = Math.Max(fMax, _lstDataSource[i]);
            return fMax;
        }

        public float GetYMin(int iStartIndex, int iEndIndex)
        {
            float fMin = float.MaxValue;

            if (_lstDataSource == null)
                return fMin;

            for (int i = iStartIndex; i < iEndIndex; i++)
                fMin = Math.Min(fMin, _lstDataSource[i]);
            return fMin;
        }
*/
        public bool Scrollable
        {
            get { return _isScrollable; }
            set { _isScrollable = value; }
        }

        public float CustomXMin
        {
            get { return _fCustomXMin; }
            set { _fCustomXMin = value; }
        }


        public float CustomYMin
        {
            get { return _fCustomYMin; }
            set { _fCustomYMin = value; }
        }

        public int XDataType
        {
            get { return _iXDataType; }
            set { _iXDataType = value; }
        }

        public int StartIndex
        {
            get { return _iStartIndex; }
            set 
            { 
                _iStartIndex = value;
                if (_drawMethod != null)
                    _drawMethod.StartIndex = value;
            }
        }

        public int EndIndex
        {
            get { return _iEndIndex; }
            set 
            { 
                _iEndIndex = value;
                if (_drawMethod != null)
                    _drawMethod.EndIndex = value;
            }
        }

        public float XMax
        {
            get
            {
                float fMax = -float.MaxValue;
                int iEndIndex;

                if (_lstXMax == null)
                    return fMax;

                if ((StartIndex == EndIndex) || (Scrollable == false))
                {
                    iEndIndex = _lstXMax.Count;
                    EndIndex = iEndIndex;
                }
                else
                {
                    iEndIndex = Math.Min(EndIndex, _lstXMax.Count);
                }

                for (int i = StartIndex; i < iEndIndex ; i++)
                    fMax = Math.Max(fMax, _lstXMax[i]);

/*
                if (_lstDataSource1 == null)
                    return fMax;

                for (int i = StartIndex; i < Math.Min(EndIndex, _lstDataSource1.Count); i++)
                    fMax = Math.Max(fMax, _lstDataSource1[i]);
 */ 
                return fMax;
            }
        }

        public float XMin
        {
            get
            {
                if (float.IsNaN(_fCustomXMin) == false)
                    return _fCustomXMin;

                float fMin = float.MaxValue;
                int iEndIndex;

                if (_lstXMin == null)
                    return fMin;

                if ((StartIndex == EndIndex) || (Scrollable == false))
                {
                    iEndIndex = _lstXMin.Count;
                    EndIndex = iEndIndex;
                }
                else
                {
                    iEndIndex = Math.Min(EndIndex, _lstXMin.Count);
                }


                for (int i = StartIndex; i < iEndIndex; i++)
                    fMin = Math.Min(fMin, _lstXMin[i]);


/*
                if (_lstDataSource1 == null)
                    return fMin;

                for (int i = StartIndex; i < Math.Min(EndIndex, _lstDataSource1.Count); i++)
                    fMin = Math.Min(fMin, _lstDataSource1[i]);
 */ 
                return fMin;
            }
        }

        public float YMax
        {
            get
            {
                float fMax = -float.MaxValue;
                int iEndIndex;

                if (_lstYMax == null)
                    return fMax;

                if ((StartIndex == EndIndex) || (Scrollable == false))
                {
                    iEndIndex = _lstYMax.Count;
                    EndIndex = iEndIndex;
                }
                else
                {
                    iEndIndex = Math.Min(EndIndex, _lstYMax.Count);
                }


                for (int i = StartIndex; i < iEndIndex; i++)
                    fMax = Math.Max(fMax, _lstYMax[i]);

/*
                if (_lstDataSource2 == null)
                    return fMax;

                for (int i = StartIndex; i < Math.Min(EndIndex, _lstDataSource2.Count); i++)
                    fMax = Math.Max(fMax, _lstDataSource2[i]);
 */ 
                return fMax;
            }
        }

        public float YMin
        {
            get
            {
                if (float.IsNaN(_fCustomYMin) == false)
                    return _fCustomYMin;

                float fMin = float.MaxValue;
                int iEndIndex;

                if (_lstYMin == null)
                    return fMin;

                if ((StartIndex == EndIndex) || (Scrollable == false))
                {
                    iEndIndex = _lstYMin.Count;
                    EndIndex = iEndIndex;
                }
                else
                {
                    iEndIndex = Math.Min(EndIndex, _lstYMin.Count);
                }


                for (int i = StartIndex; i < iEndIndex; i++)
                    fMin = Math.Min(fMin, _lstYMin[i]);

/*
                if (_lstDataSource2 == null)
                    return fMin;

                for (int i = StartIndex; i < Math.Min(EndIndex, _lstDataSource2.Count); i++)
                    fMin = Math.Min(fMin, _lstDataSource2[i]);
 */ 
                return fMin;
            }
        }

        public int XAxis
        {
            get { return _iXAxis; }
            set { _iXAxis = value; }
        }

        public int YAxis
        {
            get { return _iYAxis; }
            set { _iYAxis = value; }
        }

        public string Name
        {
            get { return _strName; }
            set { _strName = value; }
        }

        public DataTypeEnum DataField
        {
            get { return _eDataField; }
            set { _eDataField = value; }
        }

        public string BaseStudy
        {
            get { return _strBaseStudy; }
            set { _strBaseStudy = value; }
        }

        public IDataSource DataSource
        {
            get { return _dsDataSource;}
            set { _dsDataSource = value;}
        }

        public AAA.Chart.Data.IChartMeta ChartMeta
        {
            get { return _cmChartMeta; }
            set { _cmChartMeta = value; }
        }

        public ChartStyleEnum ChartStyle
        {
            get { return _eChartType;}
            set 
            { 
                _eChartType = value;
                switch (_eChartType)
                {
                    case ChartStyleEnum.Histogram:
                        _drawMethod = new HistogramChart();
                        break;
                    case ChartStyleEnum.Bar:

                        break;
                    case ChartStyleEnum.Line:
                        _drawMethod = new LineChart();
                        break;
                    case ChartStyleEnum.CandleStick:
                        _drawMethod = new CandleStickChart();
                        break;
                    case ChartStyleEnum.PriceVolume:
                        _drawMethod = new PriceVolumeChart();
                        break;

                }
            }
        }

        #endregion
    }
}
